# Copyright (c) 2025, qiushike and contributors
# For license information, please see license.txt

import frappe
from frappe import _
from frappe.model.document import Document
from frappe.utils import cint
from frappe.query_builder.functions import Sum, Now
from light_mes.api import generate_tracking_numbers
from pypika.terms import Bracket


class InitialWorkOrder(Document):
	def validate(self):
		self.update_required_items()
		self.generate_tracking_number()
		self.update_job_card()

	def update_required_items(self):
		before_save = self.get_doc_before_save()
		key = "work_orders"
		# first_opertaion = frappe.db.get_value("Work Order Operation", 
		# 	{
		# 		"parent": self.work
		# 	}
		# )
		if self.work_orders and (not before_save or before_save.get(key) != self.get(key)):
			woi = frappe.qb.DocType("Work Order Item")
			item = frappe.qb.DocType("Item")
			data = frappe.qb.from_(woi
			).join(item
			).on(woi.item_code == item.name
			).select(
				woi.item_code,
				woi.item_name,
				item.stock_uom,
				Sum(woi.required_qty).as_("qty")
			).where(
				woi.parent.isin({r.work_order for r in self.work_orders}) 
			).groupby(
				woi.item_code, item.stock_uom, woi.item_name
			).run(as_dict=1)
			self.required_items = []
			for d in data:
				self.append("required_items", d)

	def generate_tracking_number(self):
		for row in self.tracking_numbers:
			if row.work_order and not row.tracking_number:
				tracking_number_list = generate_tracking_numbers(row.work_order, 
					arg = {
						"qty": row.qty,
						"item_code": row.item_code,
						"item_name": row.item_name,
						"initial_work_order": self.name
					}
				)
				row.tracking_number = tracking_number_list[0]

	def update_job_card(self):
		jc = frappe.qb.DocType("Job Card")
		for row in self.tracking_numbers:
			if not row.job_card and row.work_order and row.tracking_number:
				jc_data = frappe.qb.from_(jc
				).select(jc.name
				).where(jc.work_order == row.work_order
				).where(Bracket(jc.tracking_number.isnull() | jc.tracking_number =="")
				).where(jc.docstatus == 0
				).orderby(jc.sequence_id
				).limit(1
				).run(pluck=1)
				if jc_data:				
					job_card_doc = frappe.get_doc("Job Card", jc_data[0])
					job_card_doc.time_logs=[]
					job_card_doc.employee = []

					job_card_doc.tracking_number = row.tracking_number
					if self.workstation:
						job_card_doc.workstation = self.workstation
					if self.employee:
						job_card_doc.append("employee", {"employee": self.employee})
					job_card_doc.append("time_logs", {"completed_qty": row.qty})
					job_card_doc.for_quantity = row.qty
					job_card_doc.save()
					row.job_card = job_card_doc.name				

	def on_submit(self):
		if not self.tracking_numbers:
			frappe.throw(_("Please maintain tracking numbers before submit"))
		for row in self.tracking_numbers:
			if row.job_card:
				job_card_doc = frappe.get_doc("Job Card", row.job_card)
				job_card_doc.submit()

@frappe.whitelist()
def create_stock_entry(docname, purpose, is_return=0):
	#docname = frappe.form_dict.get("docname")
	#仅在之前未创建过工单发料时创建工单工单，避免重复点创建按钮
	# if not frappe.db.exists('Stock Entry', 
	# 	{
	# 		'initial_work_order': docname,
	# 		'purpose': purpose
	# 	}
	# ):
	doc = frappe.get_doc("Initial Work Order", docname)	
	posting_date = frappe.utils.today()
	posting_time = frappe.utils.nowtime()
	(from_warehouse, to_warehouse) = frappe.db.get_value('Work Order', doc.work_orders[0].work_order,
		['source_warehouse', 'wip_warehouse']
	)
	is_return = cint(is_return)
	if is_return:
		(to_warehouse, from_warehouse) = (from_warehouse, to_warehouse)
	stock_entry = frappe.new_doc("Stock Entry")
	stock_entry.update({					
		"purpose": purpose,
		"posting_date": posting_date,
		"posting_time": posting_time,
		"company": doc.company,
		"from_warehouse": from_warehouse,
		"to_warehouse": to_warehouse,
		"initial_work_order": docname
	}) 
	stock_entry.set_stock_entry_type()
	for row in doc.required_items:		
		stock_uom = row.stock_uom
		stock_entry.append("items", {
			"item_code": row.item_code,
			"item_name": row.item_name,
			"uom": stock_uom,
			"stock_uom": stock_uom,
			"conversion_factor": 1,
			"s_warehouse": from_warehouse,
			"t_warehouse": to_warehouse,
			"qty": 0 if is_return else row.qty
		})		
	# doc.status = purpose
	# doc.db_update()	
	return stock_entry.as_dict()